package com.shm.singlecamera.Camera;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.graphics.ImageFormat;
import android.graphics.PixelFormat;
import android.media.Image;
import android.media.ImageReader;
import android.opengl.GLSurfaceView;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.util.Size;
import android.view.SurfaceHolder;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;

import com.shm.singlecamera.UI.AssistView;
import com.shm.singlecamera.Utils.CameraRender;

import java.nio.ByteBuffer;
import java.util.concurrent.locks.ReentrantLock;

public class ImageProcess implements ImageReader.OnImageAvailableListener {

    private static final String TAG = "ImageProcess";

    static {
        System.loadLibrary("miss");
    }

    public native void showMono(
            ByteBuffer yData, int src_stride_y,
            ByteBuffer uData, int src_stride_u,
            ByteBuffer vData, int src_stride_v,
            int stride, int width, int height,
            CameraRender cameraRender
    );

    private Activity context;
    private final GLSurfaceView cameraView;
    private final AssistView assistView;

    private final TextView frameSize;
    private final TextView inferenceTime;

    private HandlerThread backgroundThread;
    private Handler backgroundHandler;

    private Size previewTextureSize;
    private CameraRender cameraRender;

    private final ReentrantLock lock = new ReentrantLock();

    public void setPreviewSize(Size previewTextureSize) {
        this.previewTextureSize = previewTextureSize;
    }

    public ImageProcess(
            Activity context,
            GLSurfaceView cameraView,
            AssistView assistView,
            TextView frameSize,
            TextView inferenceTime){

        this.context = context;
        this.cameraView = cameraView;
        this.assistView = assistView;
        this.frameSize = frameSize;
        this.inferenceTime = inferenceTime;

        initGLSurface();
    }

    private void initGLSurface() {

        cameraView.setEGLContextClientVersion(2);
        //设置透明背景
        cameraView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
        cameraView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
        cameraRender = new CameraRender();
        cameraView.setRenderer(cameraRender);
        // 设置渲染模式为按需渲染
        cameraView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
        cameraView.getHolder().addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(@NonNull SurfaceHolder holder) {
                CameraStateMachine.setIsSurfaceAvailable(true);
            }

            @Override
            public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {

            }

            @Override
            public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
                CameraStateMachine.setIsSurfaceAvailable(false);
            }
        });
    }

    public Handler getBackgroundHandler() {
        return backgroundHandler;
    }

    public void start(){
        backgroundThread = new HandlerThread("ImageProcessing Thread");
        backgroundThread.start();
        // 线程启动后，现在可以安全地获取 Looper
        Looper backgroundLooper = backgroundThread.getLooper();
        backgroundHandler = new Handler(backgroundLooper);
    }

    public void shutdown() {
        backgroundThread.quitSafely();
        try {
            // 等待线程安全退出
            backgroundThread.join();
        } catch (InterruptedException e) {
            Log.e(TAG, String.valueOf(e));
        }
        if (backgroundHandler != null) {
            backgroundHandler.removeCallbacksAndMessages(null);
        }
    }

    
    @SuppressLint("DefaultLocale")
    @Override
    public void onImageAvailable(ImageReader reader) {
        // 确保 backgroundHandler 已经创建
        if (backgroundHandler != null) {
            backgroundHandler.post(() -> {

//                long start = System.currentTimeMillis();

                // 处理图像
                Image image = reader.acquireLatestImage();
                if (image == null) {
                    return;
                }

                lock.lock();

                process(image);

                lock.unlock();

            });
        }
    }

    private void process(Image currentImage) {

        if(currentImage.getFormat() != ImageFormat.YUV_420_888)
            return;

        // 获取当前图像时间
        double currentTime = 0.001 * System.currentTimeMillis();

        int currentWidth = currentImage.getWidth();
        int currentHeight = currentImage.getHeight();
        // 获取Image的Planes
        Image.Plane[] currentPlanes = currentImage.getPlanes();
        int currentStride = currentPlanes[1].getPixelStride();

        Image.Plane currentYPlane = currentImage.getPlanes()[0];
        Image.Plane currentUPlane = currentImage.getPlanes()[1];
        Image.Plane currentVPlane = currentImage.getPlanes()[2];

        // 渲染当前画面
        showMono(currentYPlane.getBuffer(), currentYPlane.getRowStride(),
                 currentUPlane.getBuffer(), currentUPlane.getRowStride(),
                 currentVPlane.getBuffer(), currentVPlane.getRowStride(),
                 currentStride, currentWidth, currentHeight,
                 cameraRender);

        // 释放Image
        currentImage.close();
    }

    Handler mainHandler = new Handler(Looper.getMainLooper()){
        @SuppressLint("SetTextI18n")
        @Override
        public void handleMessage(Message msg) {
            // 在此处处理消息
//            if(msg.what == 101){
//
//            }
        }
    };

    private long lastTime;

    @SuppressLint("SetTextI18n")
    public synchronized void updateInformation(){

        if(lastTime == 0){
            lastTime = System.currentTimeMillis();
            return;
        }
        long currentTime = System.currentTimeMillis();
        long costTime = currentTime - lastTime;

        context.runOnUiThread(new Runnable() {
            public void run() {
                // 该消息是子线程返回结果
                frameSize.setText("帧尺寸：" + previewTextureSize.getWidth() + "x" + previewTextureSize.getHeight());
                inferenceTime.setText("计算耗时：" + costTime + "ms");
            }
        });

        lastTime = currentTime;
    }

    public GLSurfaceView getView() {
        return cameraView;
    }

    public CameraRender getRender() {
        return cameraRender;
    }
}